home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 4 / Apprentice-Release4.iso / Demos / OOFILE / Buildable, limited OOFILE / OOFILE partial source / oofpp.cpp < prev    next >
Encoding:
Text File  |  1995-09-30  |  13.4 KB  |  685 lines  |  [TEXT/CWIE]

  1. // COPYRIGHT 1995 A.D. Software, All rights reserved
  2.  
  3. // PowerPlant Integration layer of OOFILE database
  4. #include "oofppx.hpp"  // private interface, includes public
  5. #include "oof4.hpp"    // extra field definitions
  6. #include "oofview.hpp"
  7.  
  8. #include "stdlib.h"
  9. #ifdef _Windows
  10.     #include <strstrea.h>
  11. #else
  12.     #include <strstream.h>
  13. #endif
  14. #include "fstream.h"
  15.  
  16.  
  17.  
  18.  
  19. // include PowerPlant definitions
  20. #include <LEditField.h>
  21. #include <LListBox.h>
  22. #include <LTextEdit.h>
  23. #include <UMemoryMgr.h>
  24. #include <PP_Messages.h>
  25.  
  26.  
  27. // static variables
  28. dbDocHelper*  dbDocHelper::sCurrentDoc = 0;
  29.  
  30. // -------------------------------------------------------
  31. //                 d b D o c H e l p e r
  32. // -------------------------------------------------------
  33. dbDocHelper::dbDocHelper() :
  34.     mAddFactory(0), 
  35.     mEditFactory(0), 
  36.     mBrowseFactory(0),
  37.     mInterestedInRecordChanges(0)
  38. {};
  39.  
  40.  
  41. dbDocHelper::~dbDocHelper()
  42. {
  43.     delete mAddFactory;
  44.     delete mEditFactory;
  45.     delete mBrowseFactory;
  46.     
  47. }
  48.  
  49.  
  50. // the following pair of methods hint at a need to have some more 
  51. // general dependency mechanism, probably as a mixin.
  52. // it WILL happen, once we've used this approach for a couple of apps
  53. // but will be transparent to clients of these classes anyway
  54. // as these dependencies are only within the framework
  55.  
  56. void dbDocHelper::recordHasBeenChanged(dbWindowHelper* changedBy)
  57. {
  58.     if (mInterestedInRecordChanges) {
  59.         mInterestedInRecordChanges->recordHasBeenChanged(changedBy);
  60.     }
  61. }
  62.  
  63.  
  64. void dbDocHelper::interestedInRecordChanges(dbWindowHelper* interestedParty)
  65. {
  66.     mInterestedInRecordChanges = interestedParty;
  67. }
  68.  
  69.  
  70. // slightly sloppy duplicated code for now, this area is likely to change
  71. // so not worth investing time simplifying
  72. void dbDocHelper::AdoptAddDialogFactory(dbWindowFactory* factory)
  73. {
  74. #ifdef OOF_Debug
  75.     if (mAddFactory)
  76.         dbConnect::raise("dbDocHelper::adoptAddDialogFactory replacing current factory");
  77. #endif
  78.     delete mAddFactory;
  79.     mAddFactory = factory;
  80. }
  81.  
  82.  
  83. void dbDocHelper::AdoptEditDialogFactory(dbWindowFactory* factory)
  84. {
  85. #ifdef OOF_Debug
  86.     if (mEditFactory)
  87.         dbConnect::raise("dbDocHelper::adoptEditDialogFactory replacing current factory");
  88. #endif
  89.     delete mEditFactory;
  90.     mEditFactory = factory;
  91. }
  92.  
  93.  
  94.  
  95. void dbDocHelper::AdoptBrowseWindowFactory(dbWindowFactory* factory)
  96. {
  97. #ifdef OOF_Debug
  98.     if (mBrowseFactory)
  99.         dbConnect::raise("dbDocHelper::adoptBrowseWindowFactory replacing current factory");
  100. #endif
  101.     delete mBrowseFactory;
  102.     mBrowseFactory = factory;
  103.     mMainTable = factory->mainTable();
  104. }
  105.  
  106.  
  107. bool dbDocHelper::OOFILEhandlesMessage(const Int32    inMessage, void     *ioParam)
  108. {
  109.     switch (inMessage) {
  110.     case 'dNew':
  111.         NewRecord();
  112.         return true;
  113.  
  114.     default:
  115.         return false;
  116.     }
  117.     return false;
  118. }
  119.  
  120.  
  121. LWindow* dbDocHelper::MakeBrowser()
  122. {
  123.     if (mBrowseFactory) {
  124.         sCurrentDoc = this;
  125.         return mBrowseFactory->makeWindow();
  126.     }
  127.     else
  128.         return NULL;
  129. }
  130.  
  131.  
  132. LWindow* dbDocHelper::NewRecord()
  133. {
  134.     if (mAddFactory) {
  135.         sCurrentDoc = this;
  136.         mMainTable->newRecord();
  137.         return mAddFactory->makeWindow(false);
  138.     }
  139.     else
  140.         return NULL;
  141. }
  142.  
  143.  
  144. LWindow* dbDocHelper::MakeEditor()
  145. {
  146.     if (mEditFactory) {
  147.         sCurrentDoc = this;
  148.         return mEditFactory->makeWindow(true);
  149.     }
  150.     else
  151.         return NULL;
  152. }
  153.  
  154. // -------------------------------------------------------
  155. //                 d b W i n d o w H e l p e r
  156. // -------------------------------------------------------
  157.  
  158. dbWindowHelper::dbWindowHelper()
  159. {
  160.     LinkToDoc();
  161. }
  162.                             
  163.  
  164. void dbWindowHelper::LinkToDoc()
  165. {
  166.     mBossDoc = dbDocHelper::sCurrentDoc;
  167. }
  168.  
  169.  
  170. // -------------------------------------------------------
  171. //                 d b B r o w s e H e l p e r
  172. // -------------------------------------------------------
  173.  
  174. dbBrowseHelper::dbBrowseHelper() : 
  175.     mBrowsingView(0),
  176.     mBrowserDisplay(0)
  177. {
  178.     mBossDoc->interestedInRecordChanges(this);
  179. }
  180.  
  181.  
  182. dbBrowseHelper::~dbBrowseHelper() 
  183. {
  184.     delete mBrowsingView;
  185.     delete mBrowserDisplay;
  186. }
  187.  
  188.  
  189. void dbBrowseHelper::recordHasBeenChanged(dbWindowHelper* changedBy)
  190. {
  191.     LoadBrowseData();
  192. }
  193.  
  194.  
  195. bool dbBrowseHelper::OOFILEhandlesMessage(
  196.     const Int32    inMessage,
  197.     void        *ioParam)
  198. {
  199.     switch (inMessage) {
  200.     case cmd_dbNew:
  201.         mBossDoc->NewRecord();
  202.         // scope for us to react afterwards
  203.         return true;
  204.  
  205.     case cmd_dbDoubleClick:
  206.     case cmd_dbEdit:
  207.         if (mBrowserDisplay)
  208.             mBrowsingView->source()->gotoRelativeRecord(mBrowserDisplay->selectedRow());
  209.         mBossDoc->MakeEditor();
  210.         // scope for us to react afterwards
  211.         return true;
  212.  
  213.     case cmd_dbDel:
  214.         DelRecord();
  215.         return true;
  216.  
  217.     default:
  218.         return false;
  219.     }
  220.     return false;
  221. }
  222.  
  223.  
  224. void dbBrowseHelper::DelRecord()
  225. {
  226.     SysBeep(30);  // not implemented in demo
  227. }
  228.  
  229.  
  230. void dbBrowseHelper::AdoptView(dbView* theView)
  231. {
  232.     if (mBrowsingView)
  233.         if (mBrowserDisplay)
  234.             mBrowserDisplay->changeViewTo(theView);
  235.     delete mBrowsingView;
  236.     mBrowsingView = theView;
  237. }
  238.  
  239.  
  240. void dbBrowseHelper::BrowseViewWithListBox(LListBox* theLB)
  241. {
  242. #ifdef OOF_Debug
  243.     if (mBrowserDisplay)
  244.         dbConnect::raise("dbBrowseHelper::BrowseViewWithListBox replacing current browser display");
  245. #endif
  246.     delete mBrowserDisplay;
  247.     mBrowserDisplay = new dbListBoxDisplay(theLB, mBrowsingView);
  248. }
  249.  
  250.  
  251. void dbBrowseHelper::LoadBrowseData()
  252. {
  253.     if (mBrowserDisplay) 
  254.         mBrowserDisplay->loadData();
  255. }
  256.  
  257.  
  258. // -------------------------------------------------------
  259. //                 d b E d i t H e l p e r
  260. // -------------------------------------------------------
  261.  
  262. dbEditHelper::dbEditHelper() :
  263.                             mNew(false),
  264.                             mChangingPages(false),
  265.                             mAutoSaveOnMoving(true),
  266.                             mMainTable(0)
  267. {
  268. }
  269.  
  270.  
  271. dbEditHelper::~dbEditHelper()
  272. {
  273.     mLinks.deleteAll();
  274.     delete mMainTable;
  275. }
  276.  
  277.  
  278. void dbEditHelper::LinkField(dbChar* fld, LEditField* ctl)
  279. {
  280.     mLinks.append(new dbCharLink2EditField(fld, ctl));
  281. }
  282.  
  283.  
  284. void dbEditHelper::LinkField(dbChar* fld, LTextEdit* ctl)
  285. {
  286.     mLinks.append(new dbCharLink2TextEdit(fld, ctl));
  287. }
  288.  
  289.  
  290. void dbEditHelper::LinkField(dbText* fld, LTextEdit* ctl)
  291. {
  292.     mLinks.append(new dbTextLink2TextEdit(fld, ctl));
  293. }
  294.  
  295.  
  296. void dbEditHelper::LinkField(dbLong* fld, LEditField* ctl)
  297. {
  298.     mLinks.append(new dbLongLink2EditField(fld, ctl));
  299. }
  300.  
  301.  
  302. void dbEditHelper::LinkField(dbShort* fld, LEditField* ctl)
  303. {
  304.     mLinks.append(new dbShortLink2EditField(fld, ctl));
  305. }
  306.  
  307.  
  308. void dbEditHelper::LinkField(dbDate* fld, LEditField* ctl)
  309. {
  310.     mLinks.append(new dbDateLink2EditField(fld, ctl));
  311. }
  312.  
  313.  
  314. void dbEditHelper::GoFirstRecord()
  315. {
  316.     assert(mMainTable);
  317.     if (mMainTable->atFirst()) 
  318.         SysBeep(30);
  319.     else
  320.     {
  321.         if(LeaveRecord()) {
  322.             mMainTable->first();
  323.             LoadData();
  324.         }
  325.     }
  326. }
  327.  
  328.  
  329. void dbEditHelper::GoNextRecord()
  330. {
  331.     assert(mMainTable);
  332.     if (mMainTable->atLast()) 
  333.         SysBeep(30);
  334.     else
  335.     {
  336.         if(LeaveRecord()) {
  337.             mMainTable->next();
  338.             LoadData();
  339.         }
  340.     }
  341. }
  342.  
  343.  
  344. void dbEditHelper::GoPrevRecord()
  345. {
  346.     assert(mMainTable);
  347.     if (mMainTable->atFirst()) 
  348.         SysBeep(30);
  349.     else
  350.     {
  351.         if(LeaveRecord()) {
  352.             mMainTable->prev();
  353.             LoadData();
  354.         }
  355.     }
  356. }
  357.  
  358.  
  359. void dbEditHelper::GoLastRecord()
  360. {
  361.     assert(mMainTable);
  362.     if (mMainTable->atLast()) 
  363.         SysBeep(30);
  364.     else
  365.     {
  366.         if(LeaveRecord()) {
  367.             mMainTable->last();
  368.             LoadData();
  369.         }
  370.     }
  371. }
  372.  
  373.  
  374. bool dbEditHelper::LeaveRecord()
  375. {
  376.     if(CanLeaveRecord()) {
  377.         if (mAutoSaveOnMoving)
  378.             SaveRecord();
  379.         return true;
  380.     }
  381.     else
  382.         return false;  // user-override says NO
  383. }
  384.  
  385.  
  386. void dbEditHelper::LoadData()
  387. {
  388.     assert(mMainTable);        // should be setup by now!
  389.     EnteringAboutToLoad();    // user hook
  390.     CopyFieldsToLinks();
  391.     EnteringAfterLoad();    // user hook
  392. }
  393.  
  394.  
  395. void dbEditHelper::SaveRecord()
  396. {
  397.     assert(mMainTable);        // should be setup by now!
  398.     LeavingAboutToSave();    // user hook
  399.     CopyLinksToFields();
  400.     mMainTable->saveRecord();
  401.     LeavingAfterSave();        // user hook
  402.     mBossDoc->recordHasBeenChanged(this);  // will be more intelligent later about if record is REALLY changed
  403. }
  404.  
  405.  
  406. void dbEditHelper::warnUser(ostream& os)
  407. {
  408. #ifdef _Windows
  409.     strstream oss;
  410.     oss << os.rdbuf() << ends;
  411.     char* s = oss.str();
  412.     ::MessageBox(0, s, "Warning", MB_ICONEXCLAMATION);
  413.     oss.rdbuf()->freeze(0);  // leave buffer for stream to delete
  414. #else
  415.     cout << os.rdbuf();
  416. #endif
  417. }
  418.  
  419.  
  420.  
  421. void dbEditHelper::CopyLinksToFields()
  422. {
  423.     int numLinks = mLinks.count();
  424.     for (int i=0; i<numLinks; i++) {
  425.         dbFieldLink* fl = (dbFieldLink*) (mLinks[i]);  // safe downcast
  426.         fl->copyLinkToField();        
  427.         mLinks.next();
  428.     }
  429. }
  430.  
  431.  
  432. void dbEditHelper::CopyFieldsToLinks()
  433. {
  434.     int numLinks = mLinks.count();
  435.     for (int i=0; i<numLinks; i++) {
  436.         dbFieldLink* fl = (dbFieldLink*) (mLinks[i]);  // safe downcast
  437.         fl->copyFieldToLink();
  438.         mLinks.next();
  439.     }
  440. }
  441.  
  442.  
  443. bool dbEditHelper::OOFILEhandlesMessage(
  444.     const Int32    inMessage,
  445.     void        *ioParam)
  446. {
  447.     switch (inMessage) {
  448.     case msg_OK:
  449.         if(CanLeaveRecord()) {
  450.             SaveRecord();
  451.             LCommander::GetDefaultCommander()->ProcessCommand(cmd_Close, ioParam);
  452.         }
  453.         return true;
  454.  
  455.     case msg_Cancel:
  456.             LCommander::GetDefaultCommander()->ProcessCommand(cmd_Close, ioParam);
  457.         return true;
  458.  
  459.     case cmd_dbFirst:
  460.         GoFirstRecord();
  461.         return true;
  462.  
  463.     case cmd_dbPrev:
  464.         GoPrevRecord();
  465.         return true;
  466.  
  467.     case cmd_dbNext:
  468.         GoNextRecord();
  469.         return true;
  470.  
  471.     case cmd_dbLast:
  472.         GoLastRecord();
  473.         return true;
  474.  
  475.     default:
  476.         return false;
  477.     }
  478.     return false;
  479. }
  480.  
  481.  
  482.  
  483. // -------------------------------------------------------
  484. //        d b C h a r  L i n k 2 E d i t F i e l d
  485. // -------------------------------------------------------
  486. void dbCharLink2EditField::copyFieldToLink()
  487. {
  488.     Str255 str;
  489.     mField->asStr255(str);
  490.     mLinkTo->SetDescriptor(str);
  491. }
  492.  
  493.  
  494. void dbCharLink2EditField::copyLinkToField()
  495. {
  496.     Str255 str;
  497.     mLinkTo->GetDescriptor(str);
  498.     mField->setStr255(str);
  499. }
  500.  
  501.  
  502.  
  503. // -------------------------------------------------------
  504. //        d b C h a r L i n k 2 T e x t E d i t
  505. // -------------------------------------------------------
  506. void dbCharLink2TextEdit::copyFieldToLink()
  507. {
  508.     const char* c = *mField;
  509.     Ptr p = const_cast<Ptr>(c);
  510.     mLinkTo->SetTextPtr(p, mField->fieldDataLen());
  511. }
  512.  
  513.  
  514. void dbCharLink2TextEdit::copyLinkToField()
  515. {
  516.     Handle h = mLinkTo->GetTextHandle();
  517.     StHandleLocker playSafe(h);
  518.     mField->setChars((char*) *h, GetHandleSize(h));
  519. }
  520.  
  521.  
  522. // -------------------------------------------------------
  523. //        d b T e x t L i n k 2 T e x t E d i t
  524. // -------------------------------------------------------
  525. void dbTextLink2TextEdit::copyFieldToLink()
  526. {
  527.     const char* c = *mField;
  528.     Ptr p = const_cast<Ptr>(c);
  529.     mLinkTo->SetTextPtr(p, mField->fieldDataLen());
  530. }
  531.  
  532.  
  533. void dbTextLink2TextEdit::copyLinkToField()
  534. {
  535.     Handle h = mLinkTo->GetTextHandle();
  536.     StHandleLocker playSafe(h);
  537.     mField->setChars((char*) *h, GetHandleSize(h));
  538. }
  539.  
  540.  
  541.  
  542. // -------------------------------------------------------
  543. //        d b L o n g  L i n k 2 E d i t F i e l d
  544. // -------------------------------------------------------
  545. void dbLongLink2EditField::copyFieldToLink()
  546. {
  547.     mLinkTo->SetValue(*mField);
  548. }
  549.  
  550.  
  551. void dbLongLink2EditField::copyLinkToField()
  552. {
  553.     *mField = mLinkTo->GetValue();
  554. }
  555.  
  556.  
  557.  
  558. // -------------------------------------------------------
  559. //        d b S h o r t  L i n k 2 E d i t F i e l d
  560. // -------------------------------------------------------
  561. void dbShortLink2EditField::copyFieldToLink()
  562. {
  563.     mLinkTo->SetValue(*mField);
  564. }
  565.  
  566.  
  567. void dbShortLink2EditField::copyLinkToField()
  568. {
  569.     *mField = mLinkTo->GetValue();
  570. }
  571.  
  572.  
  573.  
  574. // -------------------------------------------------------
  575. //        d b D a t e  L i n k 2 E d i t F i e l d
  576. // -------------------------------------------------------
  577. void dbDateLink2EditField::copyFieldToLink()
  578. {
  579.     Str255 str;
  580.     mField->asStr255(str);
  581.     mLinkTo->SetDescriptor(str);
  582. }
  583.  
  584.  
  585. void dbDateLink2EditField::copyLinkToField()
  586. {
  587.     Str255 str;
  588.     mLinkTo->GetDescriptor(str);
  589.     mField->setStr255(str);
  590. }
  591.  
  592.  
  593.  
  594. // -------------------------------------------------------
  595. //            d b L i s t B o x D i s p l a y
  596. // -------------------------------------------------------
  597. dbListBoxDisplay::dbListBoxDisplay(LListBox* theLB, dbView* theView) : 
  598.         mDisplay(theLB),
  599.         mView(theView),
  600.         mLoadedData(false)
  601. {
  602.     theLB->SetDoubleClickMessage(cmd_dbDoubleClick);
  603.     if (mView && theLB)
  604.         SetColWidths();
  605.  
  606. }
  607.  
  608.  
  609. void dbListBoxDisplay::loadData()
  610. // VERY, VERY coarse first attempt just to get a demo working
  611. {
  612.     mDisplay->Hide();
  613.     mLoadedData = true;
  614.     DeleteAllData();
  615.     ListHandle lh = mDisplay->GetMacListH();
  616.     ::LAddColumn(mView->count(), 0, lh);
  617.     int numRows = mView->source()->count();
  618.     ::LAddRow(numRows, 0, lh);
  619.  
  620.     mView->source()->start();  
  621.     for (int i=0; i<numRows; i++) {
  622.         LoadRow(i, false);
  623.         mView->source()->next();
  624.     }
  625.     mDisplay->SetValue(0);
  626.     mDisplay->Show();
  627. }
  628.  
  629.  
  630. void dbListBoxDisplay::LoadRow(const int row, bool insertTheRow)
  631. // again, some very inefficient code to get the demo working
  632. {
  633.     ListHandle lh = mDisplay->GetMacListH();
  634.     if (insertTheRow) 
  635.         ::LAddRow(1, row, lh);
  636.     mView->start();
  637.     Cell theCell;
  638.     theCell.v = row;
  639.     for (int col = 0; mView->more(); col++) {
  640.         dbField  *theField = (dbField  *) (mView->item(col));           // safe downcast
  641.         char* str = theField->copyAsChars();  // good test of allocator, in this loop!
  642.         theCell.h = col;
  643.         ::LSetCell(str, strlen(str), theCell, lh);
  644.         delete str;
  645.         mView->next();
  646.     }
  647. }
  648.  
  649.  
  650. void dbListBoxDisplay::DeleteAllData()
  651. {
  652.     ListHandle lh = mDisplay->GetMacListH();
  653.     ::LDelColumn(0, 0, lh);  // all cols in one go
  654.     ::LDelRow(0, 0, lh);  // all rows in one go
  655. }
  656.  
  657.  
  658. void dbListBoxDisplay::changeViewTo(dbView* theView)
  659. {
  660.     mView = theView;
  661.     SetColWidths();
  662.     if (mLoadedData)  // don't load yet if hadn't loaded other view
  663.         loadData();
  664. }
  665.  
  666.  
  667. const long dbListBoxDisplay::selectedRow() const
  668. {
  669.     return mDisplay->GetValue();
  670. }
  671.  
  672.  
  673. void dbListBoxDisplay::SetColWidths()
  674. {
  675. // logic copied from LListBox::ResizeFrameBy
  676. // which unfortunately we can't just call as it has a test to see if the cells are 
  677. // already at the default width
  678.     assert(mDisplay);
  679.     assert(mView);
  680.     ListHandle lh = mDisplay->GetMacListH();
  681.     Rect    displayRect = (**lh).rView;
  682.     Point    cellSize = (**lh).cellSize;
  683.     cellSize.h = (displayRect.right - displayRect.left) / mView->count();
  684.     ::LCellSize(cellSize, lh);
  685. }